/*
**  File: AquaWhat.c
**
**  This file is part of the AQUA program suite, which is being
**  developed in the NMR Spectroscopy Department, Bijvoet Center for 
**  Biomolecular Research, Utrecht. 
**
**
**  AUTHOR(S) : Ton Rullmann
**  VERSION   : 1.5.0
**  DATE      : Dec 16, 1997
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "Compiler.h"
#include "General.h"

#include "AquaMacros.h"
#include "AquaTypes.h"

/****************  function prototypes  ****************/

#include "AquaRange.h"
#include "AquaFuncts.h"
#include "AquaFuncts_io.h"
#include "AquaStrucset.h"
#include "MenuFuncts.h"
#include "Functs.h"

#include "AquaWhat.h"

/****************  globals  ****************/

extern Boolean  batch, iaf;                          /* import from Functs */
extern int      terseness;                           /* import from Functs */
extern Range    *range;                              /* import from AquaRange */
char            *program_name = "AquaWhat";          /* export to Functs */
char            *program_vers = aqua_version;        /* export to Functs */



/* BEGIN_EXTH */

/****************  main  ****************/
/*
**  Determine what to analyze: make a 'strucset' file containing
**  atom descriptions and coordinates.
*/

int main( int argc, char *argv[] )
{
    Strucset  Set1, Set2, Set3, *setptr;
    int       item;
    Card      lib_string;
    char      *lib_nam;
    char      *lib_nam_temp;
    char      temp_value[4];
    Menu      *oldmenu;
    Boolean   done = false, onlyone = false;
    
    enum { item_read, item_read1, item_merge, item_select, item_show, item_write,
           item_renum, item_map2aq, item_map2ex };
    static MenuItem menulist[] =
    {
        { item_EXEC,   "exec",     none, on },
        { item_SET,    "set",      none, on },
        { item_read,   "read",     none, on },
        { item_read1,  "readone",  none, on },
        { item_merge,  "merge",    none, off },
        { item_select, "select",   none, off }, 
        { item_show,   "show",     none, off }, 
        { item_write,  "write",    none, off }, 
        { item_renum,  "renum",    none, off }, 
        { item_map2aq, "maptoaq",  none, off }, 
        { item_map2ex, "maptoext", none, off }, 
        { item_QUIT,   "quit",     none, on } 
    };
    static MenuItem menulist_crdinp[] =
    {
        { item_NONE,   "none",    none, on },
        { crd_list,    "list",    none, off },
        { crd_aqua,    "aqua",    none, on }, 
        { crd_dummy,   "dummy",   none, on }, 
        { crd_pdb,     "pdb",     none, on }, 
        { crd_pdbn,    "pdbn",    none, on }, 
        { crd_pdbx,    "pdbx",    none, on }, 
        { crd_pdbm,    "pdbm",    none, on }, 
        { crd_pdbmr,   "pdbmr",   none, on }, 
        { crd_biosym,  "biosym",  none, on }
    };                          /* same as in ReadMenu - see AquaFuncts_io.c */
    static MenuItem menulist_crdout[] =
    {
        { item_NONE,   "none",    none, on },
        { crd_aqua,    "aqua",    none, on }, 
        { crd_pdb,     "pdb",     none, on }, 
        { crd_star,    "star",    none, on }, 
        { crd_pdbn,    "pdbn",    none, off }, 
        { crd_pdbx,    "pdbx",    none, off }, 
        { crd_pdbm,    "pdbm",    none, off }, 
        { crd_biosym,  "biosym",  none, off } 
    };                          /* same as in WriteMenu - see AquaFuncts_io.c */
    static MenuItem menulist_rstinp[] =
    {
        { item_NONE,   "none",      none, on }, 
        { item_aqua,   "aqua",      none, on }, 
        { item_disman, "disman",    none, on }, 
        { item_disgeo, "disgeo",    none, on }, 
        { item_diana,  "diana",     none, on }, 
        { item_xplor,  "xplor",     none, on }, 
        { item_xplori, "xplor-inv", none, on }, 
        { item_biosym, "biosym",    none, on }, 
        { item_whatif, "whatif",    none, on }, 
        { item_local,  "local",     none, on }, 
        { item_user,   "user",      none, on }, 
        { item_copy,   "copy",      none, on }
    };                      /* same as in AquaHow, AquaPseudo and GetLIBName */
    static MenuItem optionlist[] =
    {
        { opt_batch,     "batch",       logical, on }, 
        { opt_terseness, "terseness",   integer, on }, 
        { opt_prtaq,     "print",       logical, on }, 
        { opt_prtres,    "printres",    logical, on }, 
        { opt_prtlib,    "printlib",    logical, on }, 
        { opt_prtmap,    "printmap",    logical, on }, 
        { opt_rest_sel,  "rest-select", oneword, on }, 
        { opt_crdinp,    "coordinp",    oneword, on }, 
        { opt_crdout,    "coordout",    oneword, on }, 
        { opt_rstinp,    "restrinp",    oneword, on }, 
        { opt_atmlib,    "atomlib",     string,  on }, 
        { opt_find2,     "find2",       logical, on },
        { opt_element_guess_pdb, "element_guess_pdb", logical, on }
    };

    static Menu    menu =
    {
        "Main menu", "command", "Give command:", 
        sizeof(menulist)/sizeof(MenuItem)
    };
    static Menu menu_crdinp =
    {
        "Coordinp menu", "type", "Give type of coordinate input file:", 
        sizeof(menulist_crdinp)/sizeof(MenuItem)
    };
    static Menu menu_crdout =
    {
        "Coordout menu", "type", "Give type of coordinate output file:", 
        sizeof(menulist_crdout)/sizeof(MenuItem)
    };
    static Menu menu_rstinp =
    {
        "Restrinp menu", "name", "Give restraint input type:", 
        sizeof(menulist_rstinp)/sizeof(MenuItem)
    };
    static Menu options =
    {
        "Options menu", "option", "Give option:", 
        sizeof(optionlist)/sizeof(MenuItem)
    }; 
    

/* initialize */

    ProgramInit( argc, argv );
    ProjectInit();
    StrucsetInit( &Set1, "Set1", true );
    SetMenu( &menu, menulist );
    SetOptions( &options, optionlist );
    SetSubMenu( &options, opt_crdinp, &menu_crdinp, menulist_crdinp );
    SetSubMenu( &options, opt_crdout, &menu_crdout, menulist_crdout );
    SetSubMenu( &options, opt_rstinp, &menu_rstinp, menulist_rstinp );
    ModOption( opt_rstinp, "none" );
    ModOption( opt_crdinp, "none" );
    ModOption( opt_crdout, "aqua" );
    ModOption( opt_element_guess_pdb, "false" );\

    sprintf( temp_value, "%d", terseness );
    ModOption( opt_terseness, temp_value );    
    range = NULL;
    
/* the main menu loop */

    while ( true )
    {
        item = ReadMenuItem();
        switch ( item )
        {
            case item_EXEC:
		DoExec();
                break;
            case item_SET:
		ReadOption();
		batch       = OptionTrue( opt_batch );
                if ( !Check_General_Options () ) {
	            printf( "Error in main: general options set are not okay\n" );
	            MError( );
                }
                terseness   = GetOptionIVal ( opt_terseness );
                break;
	    case item_read1:
		onlyone = true;
            case item_read:
                if ( ReadMenu( &Set1, onlyone ) )
                {
                    if ( OptionTrue( opt_atmlib ) ) {
                        lib_nam_temp = "user";
                    } else {
                        lib_nam_temp = "";
                    }
                    MapAtomsInSet( &Set1, ext_to_int, lib_nam_temp);
                    EnableMenuItem( item_merge );
                    EnableMenuItem( item_show );
                    EnableMenuItem( item_write );
                    EnableMenuItem( item_select );
                    EnableMenuItem( item_renum );
                    EnableMenuItem( item_map2aq );
                    EnableMenuItem( item_map2ex );
                    DisableMenuItem( item_read );
                    DisableMenuItem( item_read1 );
                }
		onlyone = false;
                break;
	    case item_merge:
                StrucsetInit( &Set2, "Set2", true );
                if ( ReadMenu( &Set2, false ) ) {
                    if ( OptionTrue( opt_atmlib ) ) {
                        lib_nam_temp = "user";
                    } else {
                        lib_nam_temp = "";
                    }
                    MapAtomsInSet( &Set2, ext_to_int, lib_nam_temp ); 
                } else
		    break;
		StrucsetInit( &Set3, "Set3", true );
		StrucsetJoin( &Set3, &Set1, &Set2 );
		Set3.type = explo_str_data;
	        if ( IsEmptyStr( Set3.ident ) )
		    DefaultStrucsetIdent( &Set3 );
                DisableMenuItem( item_merge );
                break;
            case item_select:
                Select();
                break;
            case item_renum:
                if ( (setptr = WhichStrucset() ) )
                    RenumResidues( setptr );
                break;
	    case item_map2aq:
		oldmenu = SetOneMenu( "Give library (or - to end):" );
		done = false;
		while ( !done )
		{
		    MReadWord( lib_string );
		    if ( *lib_string == '-' || strlen( lib_string ) == 0 )
			break;
		    if ( ( setptr = WhichStrucset() ) )
		    {
			setptr->mapped = false;
			MapAtomsInSet( setptr, ext_to_int, lib_string );
			StrucsetInit( &Set2, "Set2", true );
			StrucsetSort( &Set2, setptr, setptr->molecule );
			Set2.type = orig_str_data;
			strcpy( Set2.derived, setptr->derived );
			sprintf( Set2.ident, "Atoms mapped and sorted using library <%s>", lib_string ); 
		    }
		    done = true;
		}
		ResetMenu( oldmenu );
		break;
	    case item_map2ex:
		if ( iaf )
		    puts( "Choose the atom name format:" );
		lib_nam = GetLIBName( item_NONE );
		if ( lib_nam && ( setptr = WhichStrucset() ) )
		{
		    setptr->mapped = false;
                    MapAtomsInSet( setptr, int_to_ext, lib_nam );
		}
		break;
            case item_show:
                if ( ( setptr = WhichStrucset() ) )
                    WriteMenu( setptr, true );
                break;
            case item_write:
                if ( ( setptr = WhichStrucset() ) )
                {
                    WriteMenu( setptr, false );
                    StrucsetStats( setptr );
		}
                break;
            case item_QUIT:
            case item_NULL:
                exit( 0 );
                break;
            default:
                ProcessMenuError( menu_fatal );
                break;
        }    
    }
}

/****************  Select  ****************/
/*
**  Select sub-menu: 
*/

void Select( void )
{
    char     *fct_name = "Select";
    Strucset *theSetptr, *selSetptr; 
    int      *atom_map, *residue_map;
    Menu     *oldmenu;
    FILE     *fp = NULL;
    Filnam   filnam;
    Boolean  done = false;

    oldmenu = SetOneMenu( "Give name of ranges file (or - to end):" );
    while ( !done )
    {
	MReadWord( filnam );
	if ( *filnam == '-' || strlen( filnam ) == 0 )
	    break;
	if ( ! ( done = OPENr( fp, filnam ) ) )
	{
	    printf( " * ranges file <%s> could not be opened\n", filnam );
	    MError();
	}
    }
    ResetMenu( oldmenu );
    if ( !done )
	return;

    fclose( fp );
    range = ReadRanges( filnam );

    if ( ( theSetptr = WhichStrucset() ) )
    {
	selSetptr = CREATE_NEW( Strucset, 1 );
	if ( !selSetptr )
	    NOMEM( "selSet" );
	StrucsetInit( selSetptr, "selSet", true );
	RangeStrucset( selSetptr, theSetptr, &atom_map, &residue_map );
    }
}
